#!/bin/bash

# 博客项目 Docker 启动脚本
# 用于 Jenkins 构建后自动部署

# 设置变量
CONTAINER_NAME="blog-server"
JAR_PATH="/var/jenkins_home/workspace/blog-server/blog/mojian-server/target/mojian-blog.jar"
PORT=8800
JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseSerialGC -XX:MaxMetaspaceSize=128m"
LOG_DIR="/var/jenkins_home/logs"
LOG_FILE="${LOG_DIR}/blog-deploy-$(date +%Y%m%d-%H%M%S).log"

# 创建日志目录
mkdir -p "$LOG_DIR"

# 日志函数：同时输出到控制台和日志文件
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" | tee -a "$LOG_FILE" >&2
}

log_success() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" | tee -a "$LOG_FILE"
}

log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" | tee -a "$LOG_FILE"
}

# 检测 Docker 命令是否需要 sudo
DOCKER_CMD="docker"
if ! docker ps >/dev/null 2>&1; then
    if sudo docker ps >/dev/null 2>&1; then
        DOCKER_CMD="sudo docker"
        log_info "检测到需要使用 sudo 执行 Docker 命令"
    else
        log_error "无法访问 Docker，请检查权限配置"
        log_error "提示: 需要将 Jenkins 用户添加到 docker 组，或配置 sudo 无密码执行"
        exit 1
    fi
fi

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

log_info "========================================"
log_info "开始部署博客服务..."
log_info "日志文件: $LOG_FILE"
log_info "========================================"

# 检查 jar 文件是否存在
if [ ! -f "$JAR_PATH" ]; then
    log_error "JAR 文件不存在: $JAR_PATH"
    exit 1
fi
log_success "JAR 文件检查通过: $JAR_PATH"

# 检查端口是否被占用
check_port() {
    local port=$1
    log_info "检查端口 $port 是否被 Docker 容器占用..."

    # 使用 docker ps 检查所有运行中的容器端口映射
    # 查找格式如 "0.0.0.0:8800->8800/tcp" 或 "8800/tcp" 的端口
    local conflicting_containers=$($DOCKER_CMD ps --format "{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" | grep -E ":$port->|0\.0\.0\.0:$port|::$port" || true)

    if [ ! -z "$conflicting_containers" ]; then
        # 过滤掉同名的容器（允许自己的容器占用）
        local other_containers=$(echo "$conflicting_containers" | grep -v "^${CONTAINER_NAME}\t" || true)

        if [ ! -z "$other_containers" ]; then
            log_error "端口 $port 已被其他 Docker 容器占用:"
            echo -e "容器名称\t镜像\t状态\t端口映射" | tee -a "$LOG_FILE"
            echo -e "$other_containers" | tee -a "$LOG_FILE"
            return 1
        else
            log_info "端口 $port 仅被当前容器 $CONTAINER_NAME 使用（将重新创建）"
        fi
    fi

    log_success "端口 $port 未被其他容器占用，可用"
    return 0
}

# 检查容器是否存在
check_container() {
    local container_name=$1
    log_info "检查容器 $container_name 是否存在..."

    # 检查容器是否存在（包括停止的）
    if $DOCKER_CMD ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
        local container_status=$($DOCKER_CMD ps -a --format "{{.Status}}" --filter "name=^${container_name}$")
        log_info "容器 $container_name 已存在，状态: $container_status"

        # 如果容器正在运行，先停止
        if $DOCKER_CMD ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
            log_info "正在停止运行中的容器 $container_name..."
            $DOCKER_CMD stop $container_name >> "$LOG_FILE" 2>&1
            if [ $? -eq 0 ]; then
                log_success "容器 $container_name 已停止"
            else
                log_error "停止容器 $container_name 失败"
                return 1
            fi
        fi

        # 删除容器
        log_info "正在删除容器 $container_name..."
        $DOCKER_CMD rm $container_name >> "$LOG_FILE" 2>&1
        if [ $? -eq 0 ]; then
            log_success "容器 $container_name 已删除"
        else
            log_error "删除容器 $container_name 失败"
            return 1
        fi
    else
        log_info "容器 $container_name 不存在，无需清理"
    fi
    return 0
}

# 先检查并清理旧容器（这样会释放端口）
if ! check_container $CONTAINER_NAME; then
    log_error "容器清理失败，部署终止"
    exit 1
fi

# 等待端口释放
sleep 2

# 检查端口冲突（清理容器后再次检查）
if ! check_port $PORT; then
    log_error "端口冲突检测失败，部署终止"
    exit 1
fi

# 检查并拉取 OpenJDK 8 镜像
log_info "检查 OpenJDK 8 镜像..."
if ! $DOCKER_CMD images --format "{{.Repository}}:{{.Tag}}" | grep -q "openjdk:8-jre-slim"; then
    log_info "镜像不存在，开始拉取 openjdk:8-jre-slim..."
    $DOCKER_CMD pull openjdk:8-jre-slim >> "$LOG_FILE" 2>&1
    if [ $? -eq 0 ]; then
        log_success "镜像拉取成功"
    else
        log_error "镜像拉取失败"
        exit 1
    fi
else
    log_success "镜像已存在"
fi

# 启动新容器
log_info "启动新容器 $CONTAINER_NAME..."
log_info "容器配置:"
log_info "  - 容器名称: $CONTAINER_NAME"
log_info "  - 端口映射: $PORT:$PORT"
log_info "  - JAR 路径: $JAR_PATH"
log_info "  - JAVA_OPTS: $JAVA_OPTS"

$DOCKER_CMD run -d \
    --name $CONTAINER_NAME \
    --restart=unless-stopped \
    -p $PORT:$PORT \
    -v $JAR_PATH:/app/mojian-blog.jar:ro \
    openjdk:8-jre-slim \
    java $JAVA_OPTS -jar /app/mojian-blog.jar >> "$LOG_FILE" 2>&1

if [ $? -eq 0 ]; then
    log_success "容器启动命令执行成功"
else
    log_error "容器启动命令执行失败"
    exit 1
fi

# 等待容器启动
log_info "等待容器启动（5秒）..."
sleep 5

# 检查容器状态
log_info "检查容器运行状态..."
if $DOCKER_CMD ps --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
    log_success "========================================"
    log_success "部署成功！"
    log_success "容器名称: $CONTAINER_NAME"
    log_success "服务端口: $PORT"
    log_success "访问地址: http://服务器IP:$PORT"
    log_success "日志文件: $LOG_FILE"
    log_success "========================================"

    # 显示容器信息
    log_info "容器详细信息:"
    $DOCKER_CMD ps --filter "name=^${CONTAINER_NAME}$" | tee -a "$LOG_FILE"

    # 显示容器日志（最近30行）
    log_info "容器启动日志（最近30行）:"
    $DOCKER_CMD logs --tail 30 $CONTAINER_NAME | tee -a "$LOG_FILE"
else
    log_error "========================================"
    log_error "部署失败！容器未启动"
    log_error "========================================"
    log_error "容器日志:"
    $DOCKER_CMD logs $CONTAINER_NAME 2>&1 | tee -a "$LOG_FILE"

    # 检查容器退出状态
    if $DOCKER_CMD ps -a --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
        local exit_code=$($DOCKER_CMD inspect --format='{{.State.ExitCode}}' $CONTAINER_NAME)
        log_error "容器退出代码: $exit_code"
    fi

    exit 1
fi

log_info "部署脚本执行完成"